/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package serverleilao;

import java.io.*;
import java.net.*;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Servidor {

    private static ServerSocket serverSocket = null;
    private static Socket clientSocket = null;
    // Servidor vai aceitar no maximo maxClientsCount clientes, ja que cada um criara uma thread.
    private static final int maxClientsCount = 10;
    private static final ClasseCliente[] threads = new ClasseCliente[maxClientsCount];

    public void Servidor() {
        int porta = 6990;
        try {
            serverSocket = new ServerSocket(porta);
        } catch (IOException ex) {
            System.out.println("Nao foi possivel criar o socket na porta " + porta);
        }
        while (true) {
            //aceitar novos clientes
            try {
                clientSocket = serverSocket.accept();
                int i = 0;
                for (i = 0; i < maxClientsCount; i++) {
                    if (threads[i] == null) {
                        (threads[i] = new ClasseCliente(clientSocket, threads)).start();
                        System.out.println("Novo Cliente conectado!");
                        break;
                    }
                }
                if (i == maxClientsCount) {
                    PrintStream os = new PrintStream(clientSocket.getOutputStream());
                    os.println("Muitas conexoes no momento, tenta mais tarde.");
                    os.close();
                    clientSocket.close();
                }
            } catch (IOException e) {
                System.out.println(e);
            }
        }
    }

    private class ClasseCliente extends Thread {

        private BufferedReader is = null;
        private PrintStream os = null;
        private Socket clientSocket = null;
        private final ClasseCliente[] threads;
        private int maxClientsCount;

        public ClasseCliente(Socket clientSocket, ClasseCliente[] threads) {
            this.clientSocket = clientSocket;
            this.threads = threads;
            maxClientsCount = threads.length;
        }

        public void run() {
            int maxClientsCount = this.maxClientsCount;
            ClasseCliente[] threads = this.threads;
            String[] arg;
            try {
                /*
                 * Create input and output streams for this client.
                 */
                is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                os = new PrintStream(clientSocket.getOutputStream());
                Banco b = new Banco();
                ResultSet rs;
                PreparedStatement stm;
                String query;
                /* Start the conversation between client and server. */
                while (true) {
                    String line = is.readLine();
                    if (line == null) {
                        break;
                    }
                    if (line.indexOf("/quit") != -1) {
                        try {
                            b.conn.close();
                        } catch (SQLException ex) {
                            Logger.getLogger(Servidor.class.getName()).log(Level.SEVERE, null, ex);
                        }
                        break;
                    }
                    /* 
                     * Mensagens criadas entre o servidor e cliente. 
                     * 
                     * Consultas SQL
                     */
                    if (line.startsWith("@GET")) {
                        if (line.indexOf("!maior") != -1) {
                            /*
                             * consulta que retorna o maior lance atualmente
                             */
                            try {
                                arg = line.split("\\$");
                                System.out.println("ARG 0>>>>>>" + arg[0] + " ARG 1>>>>> " + arg[1]);
                                b.conectar();
                                query = "SELECT MAX(valor) AS valor FROM lance WHERE idLeilao= ?";
                                stm = b.conn.prepareStatement(query);
                                stm.setString(1, arg[1]);
                                rs = stm.executeQuery();
                                if (rs.next()) {
                                    for (int i = 0; i < maxClientsCount; i++) {
                                        if (threads[i] != null && threads[i] == this) {
                                            threads[i].os.println(rs.getString("valor"));
                                            System.out.println("Pesquisou o maior lance atual");
                                        }
                                    }
                                } else {
                                    for (int i = 0; i < maxClientsCount; i++) {
                                        if (threads[i] != null && threads[i] == this) {
                                            threads[i].os.println("Nao encontrou o maior lance");
                                        }
                                    }
                                }

                            } catch (SQLException ex) {
                                Logger.getLogger(Servidor.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        } else if (line.indexOf("!nLances") != -1) {
                            try {
                                arg = line.split("\\$");
                                System.out.println("ARG 0>>>>>>" + arg[0] + " ARG 1>>>>> " + arg[1]);
                                b.conectar();
                                query = "SELECT COUNT(*) AS valor FROM lance WHERE idLeilao = ?";
                                stm = b.conn.prepareStatement(query);
                                stm.setString(1, arg[1]);
                                rs = stm.executeQuery();
                                if (rs.next()) {
                                    for (int i = 0; i < maxClientsCount; i++) {
                                        if (threads[i] != null && threads[i] == this) {
                                            threads[i].os.println(rs.getString("valor"));
                                            System.out.println("Pesquisou o numero de lances");
                                        }
                                    }
                                } else {
                                    for (int i = 0; i < maxClientsCount; i++) {
                                        if (threads[i] != null && threads[i] == this) {
                                            threads[i].os.println("Nao encontrou o numero de lances");
                                        }
                                    }
                                }

                            } catch (SQLException ex) {
                                Logger.getLogger(Servidor.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        } else if (line.indexOf("!vencedor") != -1) {
                            try {
                                arg = line.split("\\$");
                                System.out.println("ARG 0>>>>>>" + arg[0] + " ARG 1>>>>> " + arg[1]);
                                b.conectar();
                                query = "SELECT nome FROM cliente, leilao, lance WHERE leilao.idLeilao = lance.idLeilao AND cliente.idCliente = lance.idCliente AND lance.idLeilao = ? ORDER BY `data` DESC LIMIT 1";
                                stm = b.conn.prepareStatement(query);
                                stm.setString(1, arg[1]);
                                rs = stm.executeQuery();
                                if (rs.next()) {
                                    for (int i = 0; i < maxClientsCount; i++) {
                                        if (threads[i] != null && threads[i] == this) {
                                            threads[i].os.println(rs.getString("nome"));
                                            System.out.println("Pesquisou o vencedor " + rs.getString("nome"));
                                        }
                                    }
                                } else {
                                    for (int i = 0; i < maxClientsCount; i++) {
                                        if (threads[i] != null && threads[i] == this) {
                                            threads[i].os.println("Nao encontrou o vencedor");
                                        }
                                    }
                                }

                            } catch (SQLException ex) {
                                Logger.getLogger(Servidor.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        } else if (line.indexOf("!situacao") != -1) {
                            try {
                                arg = line.split("\\$");
                                System.out.println("ARG 0>>>>>>" + arg[0] + " ARG 1>>>>> " + arg[1]);
                                b.conectar();
                                query = "SELECT COUNT(*) as cont FROM leilao WHERE dataFinal > CURDATE() AND idLeilao = ?";
                                stm = b.conn.prepareStatement(query);
                                stm.setString(1, arg[1]);
                                rs = stm.executeQuery();
                                if (rs.next()) {
                                    for (int i = 0; i < maxClientsCount; i++) {
                                        if (threads[i] != null && threads[i] == this) {
                                            threads[i].os.println(rs.getString("cont"));
                                            System.out.println("Pesquisou a situacao que eh:" + rs.getString("cont"));
                                        }
                                    }
                                } else {
                                    for (int i = 0; i < maxClientsCount; i++) {
                                        if (threads[i] != null && threads[i] == this) {
                                            threads[i].os.println("Nao encontrou a situacao");
                                        }
                                    }
                                }

                            } catch (SQLException ex) {
                                Logger.getLogger(Servidor.class.getName()).log(Level.SEVERE, null, ex);
                            }


                        } else if (line.indexOf("!idLeilao") != -1) {
                            try {
                                b.conectar();
                                query = "SELECT idLeilao FROM leilao";
                                stm = b.conn.prepareStatement(query);
                                rs = stm.executeQuery();
                                String resultado = new String();
                                while (rs.next()) {
                                    resultado += rs.getString("idLeilao") + "$";
                                }
                                for (int i = 0; i < maxClientsCount; i++) {
                                    if (threads[i] != null && threads[i] == this) {
                                        threads[i].os.println(resultado);
                                    }
                                }

                            } catch (SQLException ex) {
                                Logger.getLogger(Servidor.class.getName()).log(Level.SEVERE, null, ex);
                            }


                        } else if (line.indexOf("!produto") != -1) {
                            try {
                                b.conectar();
                                query = "SELECT produto FROM leilao";
                                stm = b.conn.prepareStatement(query);
                                rs = stm.executeQuery();
                                String resultado = new String();
                                while (rs.next()) {
                                    resultado += rs.getString("produto") + "$";
                                }
                                for (int i = 0; i < maxClientsCount; i++) {
                                    if (threads[i] != null && threads[i] == this) {
                                        threads[i].os.println(resultado);
                                    }
                                }

                            } catch (SQLException ex) {
                                Logger.getLogger(Servidor.class.getName()).log(Level.SEVERE, null, ex);
                            }


                        } else if (line.indexOf("!descricao") != -1) {
                            try {
                                b.conectar();
                                query = "SELECT descricao FROM leilao";
                                stm = b.conn.prepareStatement(query);
                                rs = stm.executeQuery();
                                String resultado = new String();
                                while (rs.next()) {
                                    resultado += rs.getString("descricao") + "$";
                                }
                                for (int i = 0; i < maxClientsCount; i++) {
                                    if (threads[i] != null && threads[i] == this) {
                                        threads[i].os.println(resultado);
                                    }
                                }

                            } catch (SQLException ex) {
                                Logger.getLogger(Servidor.class.getName()).log(Level.SEVERE, null, ex);
                            }


                        } else if (line.indexOf("!vendedor") != -1) {
                            try {
                                b.conectar();
                                query = "SELECT cliente.nome as vend FROM cliente INNER JOIN leilao ON leilao.vendedor = cliente.idCliente";
                                stm = b.conn.prepareStatement(query);
                                rs = stm.executeQuery();
                                String resultado = new String();
                                while (rs.next()) {
                                    resultado += rs.getString("vend") + "$";
                                }
                                for (int i = 0; i < maxClientsCount; i++) {
                                    if (threads[i] != null && threads[i] == this) {
                                        threads[i].os.println(resultado);
                                    }
                                }

                            } catch (SQLException ex) {
                                Logger.getLogger(Servidor.class.getName()).log(Level.SEVERE, null, ex);
                            }


                        } else if (line.indexOf("!lanceMinimo") != -1) {
                            try {
                                b.conectar();
                                query = "SELECT lanceMinimo FROM leilao";
                                stm = b.conn.prepareStatement(query);
                                rs = stm.executeQuery();
                                String resultado = new String();
                                while (rs.next()) {
                                    resultado += rs.getString("lanceMinimo") + "$";
                                }
                                for (int i = 0; i < maxClientsCount; i++) {
                                    if (threads[i] != null && threads[i] == this) {
                                        threads[i].os.println(resultado);
                                    }
                                }

                            } catch (SQLException ex) {
                                Logger.getLogger(Servidor.class.getName()).log(Level.SEVERE, null, ex);
                            }


                        } else if (line.indexOf("!dataFinal") != -1) {
                            try {
                                b.conectar();
                                query = "SELECT dataFinal FROM leilao";
                                stm = b.conn.prepareStatement(query);
                                rs = stm.executeQuery();
                                String resultado = new String();
                                while (rs.next()) {
                                    resultado += rs.getString("dataFinal") + "$";
                                }
                                for (int i = 0; i < maxClientsCount; i++) {
                                    if (threads[i] != null && threads[i] == this) {
                                        threads[i].os.println(resultado);
                                    }
                                }

                            } catch (SQLException ex) {
                                Logger.getLogger(Servidor.class.getName()).log(Level.SEVERE, null, ex);
                            }


                        } else if (line.indexOf("!numLeiloes") != -1) {
                            try {
                                b.conectar();
                                query = "SELECT COUNT(*) AS valor FROM leilao";
                                stm = b.conn.prepareStatement(query);
                                rs = stm.executeQuery();
                                if (rs.next()) {
                                    for (int i = 0; i < maxClientsCount; i++) {
                                        if (threads[i] != null && threads[i] == this) {
                                            threads[i].os.println(rs.getString("valor"));
                                            System.out.println("Pesquisou o numero de leiloes que eh:" + rs.getString("valor"));
                                        }
                                    }
                                } else {
                                    for (int i = 0; i < maxClientsCount; i++) {
                                        if (threads[i] != null && threads[i] == this) {
                                            threads[i].os.println("Nao encontrou o numero de leiloes");
                                        }
                                    }
                                }

                            } catch (SQLException ex) {
                                Logger.getLogger(Servidor.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                        /*
                         * OUTROS METODOS DE CONSULTA DO SERVIDOR DEVERAO CONSTAR AQUI
                         * 
                         */

                    } else if (line.startsWith("@SET")) {
                        if (line.indexOf("*lance*") != -1) {
                            try {
                                arg = line.split("\\$");

                                b.conectar();
                                query = "INSERT INTO lance (idLeilao, idCliente, valor) VALUES (?, ?, ?)";
                                stm = b.conn.prepareStatement(query);
                                stm.setString(1, arg[1]);
                                stm.setString(2, arg[2]);
                                stm.setString(3, arg[3]);
                                stm.execute();
                                for (int i = 0; i < maxClientsCount; i++) {
                                    if (threads[i] != null && threads[i] == this) {
                                        threads[i].os.println("OK");
                                    }
                                }
                            } catch (SQLException ex) {
                                Logger.getLogger(Servidor.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        } else if (line.indexOf("*leilao*") != -1) {
                            try {
                                arg = line.split("\\$");
                                b.conectar();
                                query = "INSERT INTO leilao (produto, descricao, vendedor, lanceMinimo, dataFinal) VALUES ('" + arg[1] + "', '" + arg[2] + "', '" + arg[3] + "', '" + arg[4] + "', '" + arg[5] + "')";
                                stm = b.conn.prepareStatement(query);
                                stm.execute();

                                for (int i = 0; i < maxClientsCount; i++) {
                                    if (threads[i] != null && threads[i] == this) {
                                        threads[i].os.println("OK");
                                    }
                                }


                            } catch (SQLException ex) {
                                Logger.getLogger(Servidor.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    } else if (line.startsWith("@LOGIN")) {

                        try {
                            arg = line.split("\\$");
                            b.conectar();
                            query = "SELECT idCliente FROM cliente WHERE login = ? AND senha = ?";
                            stm = b.conn.prepareStatement(query);
                            stm.setString(1, arg[1]);
                            stm.setString(2, arg[2]);
                            rs = stm.executeQuery();
                            if (rs.next()) {
                                for (int i = 0; i < maxClientsCount; i++) {
                                    if (threads[i] != null && threads[i] == this) {
                                        threads[i].os.println(rs.getString("idCliente"));
                                    }
                                }
                            } else {
                                for (int i = 0; i < maxClientsCount; i++) {
                                    if (threads[i] != null && threads[i] == this) {
                                        threads[i].os.println("false");
                                    }
                                }

                            }
                        } catch (SQLException ex) {
                            Logger.getLogger(Servidor.class.getName()).log(Level.SEVERE, null, ex);
                        }

                    } else {

                        for (int i = 0; i < maxClientsCount; i++) {
                            if (threads[i] != null && threads[i] == this) {
                                threads[i].os.println("*** Nao entendi sua requisicao ***");
                            }
                        }
                    }

                }
                System.out.println("Menos um cliente!");

                /*
                 * Clean up. Set the current thread variable to null so that a new client
                 * could be accepted by the server.
                 */
                synchronized (this) {
                    for (int i = 0; i < maxClientsCount; i++) {
                        if (threads[i] == this) {
                            threads[i] = null;
                        }
                    }
                }
                /*
                 * Close the output stream, close the input stream, close the socket.
                 */
                is.close();
                os.close();
                clientSocket.close();
            } catch (IOException e) {
                System.out.println("ERRO: " + e);
            }
        }
    }
}